###############################################################################
# version: v1.0.1
set $mflash_version = "v1.1.0"

###############################################################################
# Name max has 50 chars.
set $mflash_name = (char[50])""
# The number of flash controllers.
set $mflash_ctr_num = 0
# The max number of flash controllers is 5.
set $mflash_ctr_base    = (unsigned int[5]){0}
set $mflash_flash_start = (unsigned int[5]){0}
set $mflash_flash_end   = (unsigned int[5]){0}
set $mflash_info_start  = (unsigned int[5]){0}
set $mflash_info_end    = (unsigned int[5]){0}
set $mflash_sector      = (unsigned int[5]){0}

###############################################################################
# Config mflash for mce
define mflash_config_mce_core0
	set $mflash_name        = "mce core0 ck803"
	set $mflash_ctr_num     = 2
	set $mflash_ctr_base    = {0x40002000, 0x40002000}
	set $mflash_flash_start = {0x10000000, 0x00000000}
	set $mflash_flash_end   = {0x1001FFFF, 0x00000000}
	set $mflash_info_start  = {0x00000000, 0x10020000}
	set $mflash_info_end    = {0x00000000, 0x100207FF}
	set $mflash_sector      = {0x400,      0x100}
end

###############################################################################
# Check addr and get controller base addr
# $arg0: operate addr
define _mflash_get_base
	set $mflash_ctr_addr = 0
	if $mflash_ctr_num == 0
		echo Do "mflash_config*" first\n
	else
		set $mflash_i = 0
		while $mflash_i < $mflash_ctr_num
			if ($arg0 >= $mflash_flash_start[$mflash_i]) && \
			   ($arg0 <= $mflash_flash_end[$mflash_i])
				set $mflash_ctr_addr = $mflash_ctr_base[$mflash_i]
				set $mflash_sector_size = $mflash_sector[$mflash_i]
				set $mflash_i = $mflash_ctr_num
			else
				if ($arg0 >= $mflash_info_start[$mflash_i]) && \
				   ($arg0 <= $mflash_info_end[$mflash_i])
					set $mflash_ctr_addr = $mflash_ctr_base[$mflash_i]
					set $mflash_sector_size = $mflash_sector[$mflash_i]
					set $mflash_i = $mflash_ctr_num
				end
			end
			set $mflash_i++
		end
		if $mflash_ctr_addr == 0
			echo $arg0 is not at range of:\n
			set $mflash_i = 0
			while $mflash_i < $mflash_ctr_num
				printf "flash: 0x%08X - 0x%08X\n", \
					$mflash_flash_start[$mflash_i], $mflash_flash_end[$mflash_i]
				printf "info : 0x%08X - 0x%08X\n", \
					$mflash_info_start[$mflash_i], $mflash_info_end[$mflash_i]
				set $mflash_i++
			end
		end
	end
end

###############################################################################
define mflash_version
	p $mflash_version
end

###############################################################################
# Print config info
define mflash_config
	if $mflash_ctr_num
		set $mflash_i = 0
		echo Name:
		while $mflash_name[$mflash_i]
			printf "%c", $mflash_name[$mflash_i]
			set $mflash_i++
		end
		printf "\n%d range%c:\n", $mflash_ctr_num, $mflash_ctr_num==1?0:'s'
		set $mflash_i = 0
		while $mflash_i < $mflash_ctr_num
			printf "sector: %d\n", $mflash_sector[$mflash_i]
			printf "flash: 0x%08X - 0x%08X\n", \
				$mflash_flash_start[$mflash_i], $mflash_flash_end[$mflash_i]
			printf "info : 0x%08X - 0x%08X\n", \
				$mflash_info_start[$mflash_i], $mflash_info_end[$mflash_i]
			set $mflash_i++
		end
	else
		echo None config info, do "mflash_config*" first.\n
	end
end

###############################################################################
# Disable mflash cmd
define mflash_config_reset
	set $mflash_ctr_num = 0
end

document mflash_config_reset
Usage: mflash_config_reset
Set all flash commands disable.
end

###############################################################################
# Erase sector
# $arg0: erase addr
define mflash_erase_sector
	dont-repeat
	_mflash_get_base $arg0
	if $mflash_ctr_addr
		set $mflash_i = 20
		while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
			set $mflash_i--
		end
		if $mflash_i == 0
			echo flash is busy\n
		else
			# Don't need $arg0 align mflash_sector_size, and can write any value.
			#set *($arg0 & (~($mflash_sector_size-1))) = 0x21423410
			set *$arg0 = 0
			set *($mflash_ctr_addr+4) = 2
			set $mflash_i = 20
			while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
				set $mflash_i--
			end
			if $mflash_i == 0
				echo erase sector timeout\n
			end
		end
	end
end

document mflash_erase_sector
Usage: mflash_erase_sector [addr]
like:  mflash_erase_sector 0x10000010
Erase the sector which include \addr, \addr need align.
end

###############################################################################
# Erase chip
# $arg0: erase addr
define mflash_erase_chip
	dont-repeat
	_mflash_get_base $arg0
	if $mflash_ctr_addr
		set $mflash_i = 20
		while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
			set $mflash_i--
		end
		if $mflash_i == 0
			echo flash is busy\n
		else
			set *($mflash_ctr_addr+4) = 3
			set $mflash_i = 40
			while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
				set $mflash_i--
			end
			if $mflash_i == 0
				echo erase chip timeout\n
			end
		end
	end
end

document mflash_erase_chip
Usage: mflash_erase_chip [addr]
like:  mflash_erase_chip 0x10000000
Erase chip.
end

###############################################################################
# Program word
# $arg0: program addr, align 4
# $arg1: program value, uint32_t
define mflash_program_word
	dont-repeat
	_mflash_get_base $arg0
	if $mflash_ctr_addr
		set $mflash_i = 20
		while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
			set $mflash_i--
		end
		if $mflash_i == 0
			echo flash is busy\n
		else
			if $arg0 & 0x3
				echo $arg0 not align 4\n
			else
				set $mflash_i = *$arg0
				if ($mflash_i & $arg1) != $arg1
					printf "$arg0 value is: 0x%08X, can't write $arg1.\n", \
					       $mflash_i
				else
					set *$arg0 = $arg1
					set *($mflash_ctr_addr+4) = 1
					set $mflash_i = 5
					while ((*$mflash_ctr_addr) & 1) && $mflash_i
						set $mflash_i--
					end
					if $mflash_i == 0
						echo program word timeout\n
					end
					set $mflash_i = *$arg0
					if $mflash_i != $arg1
						printf "$arg0 value is: 0x%08X, write $arg1 error.\n",\
						        $mflash_i
					end
				end
			end
		end
	end
end

document mflash_program_word
Usage: mflash_program_word [addr] [value]
like:  mflash_program_word 0x10000400 0x1A2B3C
Write a word \value to the \addr, \addr need align 4.
It will check before and after write. See "mflash_program_word_force".
end

###############################################################################
# Program word force
# $arg0: program addr, align 4
# $arg1: program value, uint32_t
define mflash_program_word_force
	dont-repeat
	_mflash_get_base $arg0
	if $mflash_ctr_addr
		while ((*$mflash_ctr_addr) & 0x8) && $mflash_i
			set $mflash_i--
		end
		if $mflash_i == 0
			echo flash is busy\n
		else
			if $arg0 & 0x3
				echo $arg0 not align 4\n
			else
				set $mflash_i = *$arg0
				set *$arg0 = $arg1
				set *($mflash_ctr_addr+4) = 1
				set $mflash_i = 5
				while ((*$mflash_ctr_addr) & 1) && $mflash_i
					set $mflash_i--
				end
				if $mflash_i == 0
					echo program word timeout\n
				end
				set $mflash_i = *$arg0
				if $mflash_i != $arg1
					printf "$arg0 value is: 0x%08X, write $arg1 error.\n", $mflash_i
				end
			end
		end
	end
end

document mflash_program_word_force
Usage: mflash_program_word_force [addr] [value]
like:  mflash_program_word_force 0x10000400 0x1A2B3C
Write a word \value to the \addr, \addr need align 4.
It only check after write, see "mflash_program_word".
end

